import { jobGoto } from "../../../job/goto";
import { jobSpread } from "../../../job/spread";
import { spawnCreep } from "../../../role/spawn";
import { GroupClusterIndependent } from "../clusters/independent";
import { GroupTerminal } from "../terminal_group";

const SPAWNING=0;
const MOVE_TO=2;
const ASSEMBLE=4;
const GO_IN=6;
const CLAIMING=8;
const BUILD_SPAWN=10;
const RECYCLE=12;

const stages=[
    SPAWNING,
    MOVE_TO,
    ASSEMBLE,
    GO_IN,
    CLAIMING,
    BUILD_SPAWN,
    RECYCLE,
];

export class GroupClaimer extends GroupTerminal{
    // static defaultCreepCount=4;
    get maxSize(){
        return 2;
    }
    /**
     * 
     * @param {string} targetRoomName 
     */
    constructor(spawnRoom=undefined, targetRoomName=undefined){
        super(spawnRoom);
        if(targetRoomName!=undefined){
            this.targetRoomName=targetRoomName;
            this.stage=stages[0];
        }
    }
    serialize(){
        return {
            super: super.serialize(), 
            targetRoomName: this.targetRoomName,
            stage: this.stage,
        };
    }
    deserialize(obj){
        super.deserialize(obj.super);
        this.targetRoomName=obj.targetRoomName;
        this.stage=obj.stage;
        return this;
    }

    spawn(){
        if(this.stage==SPAWNING){
            return ERR_INVALID_TARGET;
        }
        if(this.size>=this.maxSize){
            return ERR_INVALID_TARGET;
        }
        let newCreep=spawnCreep(this.spawnRoom,{
            require:[CLAIM,CARRY,WORK,MOVE,MOVE,MOVE],
            move: .50,
            claim: .20,
            carry: .15,
            work: .15,
        },{
            memory:{
                role: 'claimer',
            }
        });
    }

    run(){
        let gotoOpts={visualizePathStyle:{stroke:"#ff9900"}};
        let targetRoom;
        switch(this.stage){
            case SPAWNING:
                for(let creep of this.creeps){
                    jobSpread.run(creep);
                }
                if(this.size()>=this.maxSize){
                    this.stage=MOVE_TO;
                }else{
                    break;
                }
            case MOVE_TO:
                let targetPos=new RoomPosition(24,24,this.targetRoomName);
                let exits=Game.map.describeExits(this.targetRoomName);
                let reached=false;
                for(let creep of this.creeps){
                    for(let direction in exits){
                        if(exits[direction]==creep.room.name){
                            reached=true;
                            this.stage=ASSEMBLE;
                            break;
                        }
                    }
                    jobGoto.run(creep, [targetPos], gotoOpts);
                }
                if(reachedCount===this.size){
                    this.stage=ASSEMBLE
                }
                break;
            case ASSEMBLE:
                //todo: assemble before go into the target room
                this.stage=GO_IN;
                // break;
            case GO_IN:
                //todo: make sure all creep break in the same time
                this.stage=CLAIMING;
                // break;
            case CLAIMING:
                targetRoom=Game.rooms[this.targetRoomName];
                for(let creep of this.creeps){
                    if(!targetRoom){
                        jobGoto.run(creep, [targetPos], gotoOpts);
                    }else{
                        if(creep.claimController(targetRoom.controller)!=OK){
                            jobGoto.run(creep, [targetRoom.controller], gotoOpts);
                        }
                    }
                }
                if(targetRoom.controller.my){
                    this.stage=BUILD_SPAWN;
                }
                break;
            case BUILD_SPAWN:
                targetRoom=Game.rooms[this.targetRoomName];
                if(targetRoom.find(FIND_MY_SPAWNS).length>0){
                    let newIndependent=new GroupClusterIndependent(targetRoom);
                    
                    Game.groups.add(newIndependent);//todo: new mem structure
                    let harvesters=newIndependent.workerGroup.harvesterGroupCluster.harvesters;
                    if(harvesters.length==0){
                        throw new Error('you just claimed a sourceless room: '+targetRoom);
                    }
                    for(let harvesterGroup of harvesters){
                        while(harvesterGroup.maxSize<harvesterGroup.size){
                            let creep = this.creeps.pop();
                            if(!creep){
                                break;
                            }
                            harvesterGroup.addCreep(creep);
                        }
                    }
                    this.stage=RECYCLE;
                }
                break;
            case RECYCLE:
                this.remove();
                break;
            default:
                throw new Error('unknown stage constant');
        }
        return OK;
    }
    remove(){
        for(let creep of this.creeps){
            creep.memory.role="suicide";
        }
        Game.groups.remove(this);//todo: new mem structure
    }
}